#pragma once

#include "Misc/EngineEditorMacros.h"
#include "Widgets/EditableTextWidget.h"
#include "EditorDragableSpinWidget.m.h"

class RFont;


//the editable float widget, user can drag to change value
RCLASS()
class REditorDragableSpinWidget : public RWidget
{
    ROBJECT
public:
    REditorDragableSpinWidget();

    //text when user not editing
    RFIELD()
    TWidgetAttribute<float> Value;

    RFIELD()
    TWidgetAttribute<float> MinValue=std::numeric_limits<float>::lowest();

    RFIELD()
    TWidgetAttribute<float> MaxValue=std::numeric_limits<float>::max();

    //how much value will change when user drag
    RFIELD()
    TWidgetAttribute<float> Step=1;

    RFIELD()
    TWidgetAttribute<bool> IsInteger=false;
    
    RFIELD()
    TScriptDelegate<void(ETextEditStopReason,float )> OnAccepted;


    RFIELD()
    TWidgetAttribute<TSharedObjectPtr<RFont>> Font;

    RFIELD()
    TWidgetAttribute<int64_t> FontSize=16;

    RFIELD()
    TWidgetAttribute<SColor> Color=SColor::White;

    RFIELD()
    TWidgetAttribute<ETextHorizontalAlignment>HorizontalAlignment= ETextHorizontalAlignment::Left;
    
    RFIELD()
    TWidgetAttribute<ETextVerticalAlignment> VerticalAlignment=ETextVerticalAlignment::Top;

    RFIELD()
    TWidgetAttribute<float> CursorWidth=2;

    RFIELD()
    TWidgetAttribute<SColor> CursorColor=SColor::White;

    void StartEdit();

    void Accept();
    void CancelEdit();

    bool IsEditing() ;

    bool IsHovered() ;
protected:
    void PaintSelf(uint16_t& InZOrder,const SRect& InClipArea) override;
    TWeakObjectPtr<RMouseWidget> Mouse;
    TWeakObjectPtr<RKeyboardWidget> Keyboard;

    CString EditingString;

    bool bIsEditing=false;

    virtual void CalculatePresentPositionAndSize() override;
    void ArrangeGlyphs();


    CStaticTextArranger TextArranger;

    void OnFocused() ;
    void OnUnfocused() ;
    bool ProcessTextInput(const STextInputEvent& BoardkeyEvent) ;
    bool ProcessKeyInput(const SKeyboardEvent& BoardkeyEvent) ;

    void ForceShowCursor();
    void HideCursor();

    // character's index  that at right side of cursor
    int64_t CursorPosition=0; 
    //is cursor visible
    bool bShowCursor=false;
    //time is auto increase, if > CursorBlinkTime, will reset to 0
    //and toggle bShowCursor
    float CursorTime=0; 
    const float CursorBlinkTime=0.5f;
    SRect CursorRect;

    TSharedObjectPtr<RFont> GetRenderingFont();

    virtual void Tick(float DeltaSeconds) override;

    bool bCanDrag=true;
    bool bDragging=false;
};